home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / timer.c < prev    next >
C/C++ Source or Header  |  1991-10-26  |  4KB  |  208 lines

  1. /* @(#) $Header: timer.c,v 1.9 91/10/25 15:01:27 deyke Exp $ */
  2.  
  3. /* General purpose software timer facilities
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include <stdio.h>
  7. #include <time.h>
  8. #include "global.h"
  9. #include "timer.h"
  10. #include "proc.h"
  11. #include "mbuf.h"
  12. #include "commands.h"
  13. #include "daemon.h"
  14. #include "hardware.h"
  15. #include "socket.h"
  16.  
  17. int32 Msclock;
  18. int32 Secclock;
  19.  
  20. /* Head of running timer chain.
  21.  * The list of running timers is sorted in increasing order of expiration;
  22.  * i.e., the first timer to expire is always at the head of the list.
  23.  */
  24. static struct timer *Timers;
  25.  
  26. static void t_alarm __ARGS((void *x));
  27.  
  28. /* Process that handles clock ticks */
  29. void
  30. timerproc(i,v1,v2)
  31. int i;
  32. void *v1,*v2;
  33. {
  34.     register struct timer *t;
  35.     int32 bugfix;
  36.     struct timeval tv;
  37.     struct timezone tz;
  38.  
  39.     for(;;){
  40.  
  41.         fflush(stdout); /* And flush out stdout too */
  42.  
  43.         gettimeofday(&tv, &tz);
  44.         Secclock = tv.tv_sec;
  45.         Msclock = 1000 * Secclock + tv.tv_usec / 1000;
  46.  
  47.         while((t = Timers) && (bugfix = t->expiration - Msclock) <= 0) {
  48.             if (Timers = t->next)
  49.                 Timers->prev = NULLTIMER;
  50.             t->state = TIMER_EXPIRE;
  51.             if(t->func)
  52.                 (*t->func)(t->arg);
  53.         }
  54.         pwait(NULL);    /* Let them run before handling more ticks */
  55.     }
  56. }
  57. /* Start a timer */
  58. void
  59. start_timer(t)
  60. struct timer *t;
  61. {
  62.     register struct timer *tnext;
  63.     struct timer *tprev = NULLTIMER;
  64.     int32 bugfix;
  65.  
  66.     if(t == NULLTIMER)
  67.         return;
  68.     if(t->state == TIMER_RUN)
  69.         stop_timer(t);
  70.     if(t->duration <= 0)
  71.         return;         /* A duration value of 0 disables the timer */
  72.  
  73.     t->expiration = Msclock + t->duration;
  74.     t->state = TIMER_RUN;
  75.  
  76.     /* Find right place on list for this guy. Once again, note use
  77.      * of subtraction and comparison with zero rather than direct
  78.      * comparison of expiration times.
  79.      */
  80.     for(tnext = Timers;tnext != NULLTIMER;tprev=tnext,tnext = tnext->next){
  81.         if((bugfix = tnext->expiration - t->expiration) >= 0)
  82.             break;
  83.     }
  84.     /* At this point, tprev points to the entry that should go right
  85.      * before us, and tnext points to the entry just after us. Either or
  86.      * both may be null.
  87.      */
  88.     if((t->prev = tprev) == NULLTIMER)
  89.         Timers = t;             /* Put at beginning */
  90.     else
  91.         tprev->next = t;
  92.  
  93.     if (t->next = tnext)
  94.         tnext->prev = t;
  95. }
  96. /* Stop a timer */
  97. void
  98. stop_timer(timer)
  99. struct timer *timer;
  100. {
  101.  
  102.     if(timer == NULLTIMER || timer->state != TIMER_RUN)
  103.         return;
  104.  
  105.     if(timer->prev)
  106.         timer->prev->next = timer->next;
  107.     else
  108.         Timers = timer->next;   /* Was first on list */
  109.  
  110.     if(timer->next)
  111.         timer->next->prev = timer->prev;
  112.  
  113.     timer->state = TIMER_STOP;
  114. }
  115. /* Return milliseconds remaining on this timer */
  116. int32
  117. read_timer(t)
  118. struct timer *t;
  119. {
  120.     int32 remaining;
  121.  
  122.     if(t == NULLTIMER || t->state != TIMER_RUN)
  123.         return 0;
  124.  
  125.     if((remaining = t->expiration - Msclock) <= 0)
  126.         return 0;       /* Already expired */
  127.     else
  128.         return remaining;
  129. }
  130. int32
  131. next_timer_event()
  132. {
  133.     if (Timers)
  134.         return read_timer(Timers);
  135.     else
  136.         return 0x7fffffff;
  137. }
  138. /* Delay process for specified number of milliseconds.
  139.  * Normally returns 0; returns -1 if aborted by alarm.
  140.  */
  141. int
  142. Xpause(ms)
  143. int32 ms;
  144. {
  145.     int val;
  146.  
  147.     if(Curproc == NULLPROC || ms <= 0)
  148.         return 0;
  149.     Xalarm(ms);
  150.     /* The actual event doesn't matter, since we'll be alerted */
  151.     while(Curproc->alarm.state == TIMER_RUN){
  152.         if((val = pwait(Curproc)) != 0)
  153.             break;
  154.     }
  155.     Xalarm(0L); /* Make sure it's stopped, in case we were killed */
  156.     return (val == EALARM) ? 0 : -1;
  157. }
  158. static void
  159. t_alarm(x)
  160. void *x;
  161. {
  162.     alert((struct proc *)x,EALARM);
  163. }
  164. /* Send signal to current process after specified number of milliseconds */
  165. void
  166. Xalarm(ms)
  167. int32 ms;
  168. {
  169.     if(Curproc != NULLPROC){
  170.         set_timer(&Curproc->alarm,ms);
  171.         Curproc->alarm.func = t_alarm;
  172.         Curproc->alarm.arg = (char *)Curproc;
  173.         start_timer(&Curproc->alarm);
  174.     }
  175. }
  176. /* Convert time count in seconds to printable days:hr:min:sec format */
  177. char *
  178. tformat(t)
  179. int32 t;
  180. {
  181.     static char buf[17],*cp;
  182.     unsigned int days,hrs,mins,secs;
  183.     int minus;
  184.  
  185.     if(t < 0){
  186.         t = -t;
  187.         minus = 1;
  188.     } else
  189.         minus = 0;
  190.  
  191.     secs = t % 60;
  192.     t /= 60;
  193.     mins = t % 60;
  194.     t /= 60;
  195.     hrs = t % 24;
  196.     t /= 24;
  197.     days = t;
  198.     if(minus){
  199.         cp = buf+1;
  200.         buf[0] = '-';
  201.     } else
  202.         cp = buf;
  203.     sprintf(cp,"%u:%02u:%02u:%02u",days,hrs,mins,secs);
  204.  
  205.     return buf;
  206. }
  207.  
  208.